package com.itheima.case2.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SqlSessionUtil {

    private static SqlSessionFactory factory;

    static {
        //实例化工厂建造类
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //读取核心配置文件
        try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
            //创建工厂对象
            factory = builder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到会话对象
     *
     * @return 会话对象 : 自动提交事务
     */
    public static SqlSession getSession() {
        return factory.openSession(true);
    }

    /**
     * 得到会话对象
     *
     * @param isAutoCommit 是否自动提交事务
     */
    public static SqlSession getSession(boolean isAutoCommit) {
        return factory.openSession(isAutoCommit);
    }

    /*
     *   提交事务并关闭session
     * */
    public static void commitAndClose(SqlSession session) {
        if (session != null) {
            session.commit();
            session.close();
        }
    }

    /*
     *   回滚事务并关闭session
     * */
    public static void rollbackAndClose(SqlSession session) {
        if (session != null) {
            session.rollback();
            session.close();
        }
    }



    //通过动态代理+泛型编程简化Mybatisbiuanc
    //原理获取mapper的代理对象，从而对mapper的方法增强
    //方法参数clazz表示方法getMapper(UserMapper.class)的参数UserMapper.class
    public static <T> T getProxyMapper(Class<T> clazz){

        //获取clazz的类加载器
        ClassLoader classLoader = clazz.getClassLoader();
        //
        Class<?>[] interfaces = {clazz};//{UserMapper.class}

        /**
         * 参数1:类加载器,一般被代理对象的类加载器
         * 参数2:接口,被代理对象实现的结构
         * 参数3:调用处理器,处理UserMapper接口的增强方法，findUserByPage findAllUserCount等
         */

        T proxyMapper =(T)Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {

            /*
                参数：
                    method ：UserMapper接口的方法findUserByPage findAllUserCount等
                    args：UserMapper接口的方法findUserByPage findAllUserCount等的参数
             */

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                //获取sqlSession对象
                SqlSession session = getSession();
                //获取猿来的mapper对象
                Object mapper = session.getMapper(clazz);

                Object res = method.invoke(mapper, args);

                session.close();

                return res;
            }


        });

        return proxyMapper;



    }




}
